/*=========================================================================
UberSim Source Code Release
-------------------------------------------------------------------------
Copyright (C) 2002 Manuela Veloso, Brett Browning, Mike Bowling,
                   James Bruce; {mmv, brettb, mhb, jbruce}@cs.cmu.edu
                   Erick Tryzelaar {erickt}@andrew.cmu.edu
School of Computer Science, Carnegie Mellon University
-------------------------------------------------------------------------
This software is distributed under the GNU General Public License,
version 2.  If you do not have a copy of this licence, visit
www.gnu.org, or write: Free Software Foundation, 59 Temple Place,
Suite 330 Boston, MA 02111-1307 USA.  This program is distributed
in the hope that it will be useful, but WITHOUT ANY WARRANTY,
including MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-------------------------------------------------------------------------*/

#include "mmgr.h"

#include "Vector3.h"

/*******************************/

const Vector3 Vector3::ZERO   = Vector3 (0.0, 0.0, 0.0);
const Vector3 Vector3::UNIT_X = Vector3 (1.0, 0.0, 0.0);
const Vector3 Vector3::UNIT_Y = Vector3 (0.0, 1.0, 0.0);
const Vector3 Vector3::UNIT_Z = Vector3 (0.0, 0.0, 1.0);

/*******************************/

Vector3::Vector3 ()
{
}

/*******************************/

Vector3::Vector3 (Real x, Real y, Real z)
{
	this->x = x;
	this->y = y;
	this->z = z;
}

/*******************************/

Vector3::Vector3 (const Real* vector)
{
	this->x = vector[0];
	this->y = vector[1];
	this->z = vector[2];
}

/*******************************/

Vector3::Vector3 (const Vector3& vector)
{
	x = vector.x;
	y = vector.y;
	z = vector.z;
}

/*******************************/

Vector3::~Vector3 ()
{
}

/*******************************/

Real& Vector3::operator [] (const unsigned int i) const
{
	return ((Real*)this)[i];
}


/*******************************/

void Vector3::set(Real _x, Real _y, Real _z)
{
  x = _x;
  y = _y;
  z = _z;
}

/*******************************/

Vector3::operator Real* ()
{
	return (Real*)this;
}

/*******************************/

const bool Vector3::operator == (const Vector3& vector) const
{
	return x == vector.x && y == vector.y && z == vector.z;
}

/*******************************/

const bool Vector3::operator != (const Vector3& vector) const
{
	return !(*this == vector);
}

/*******************************/

const Vector3& Vector3::operator = (const Vector3& vector)
{
	x = vector.x;
	y = vector.y;
	z = vector.z;

	return *this;
}

/*******************************/

const Vector3& Vector3::operator += (const Real scalar)
{
	x += scalar;
	y += scalar;
	z += scalar;

	return *this;
}

/*******************************/

const Vector3& Vector3::operator += (const Vector3& vector)
{
	x += vector.x;
	y += vector.y;
	z += vector.z;

	return *this;
}

/*******************************/

const Vector3& Vector3::operator -= (const Real scalar)
{
	x -= scalar;
	y -= scalar;
	z -= scalar;

	return *this;
}

/*******************************/

const Vector3& Vector3::operator -= (const Vector3& vector)
{
	x -= vector.x;
	y -= vector.y;
	z -= vector.z;

	return *this;
}

/*******************************/

const Vector3& Vector3::operator *= (const Real scalar)
{
	x *= scalar;
	y *= scalar;
	z *= scalar;

	return *this;
}

/*******************************/

const Vector3& Vector3::operator /= (const Real scalar)
{
	Real inverse = 1.0 / scalar;

	x *= inverse;
	y *= inverse;
	z *= inverse;

	return *this;
}

/*******************************/

const Vector3 Vector3::operator - () const
{
	return Vector3 (-x, -y, -z);
}

/*******************************/

const Vector3 Vector3::operator + (const Real scalar) const
{
	return Vector3 (x + scalar, y + scalar, z + scalar);
}

/*******************************/

const Vector3 Vector3::operator + (const Vector3& vector) const
{
	return Vector3 (x + vector.x, y + vector.y, z + vector.z);
}

/*******************************/

const Vector3 Vector3::operator - (const Real scalar) const
{
	return Vector3 (x - scalar, y - scalar, z - scalar);
}

/*******************************/

const Vector3 Vector3::operator - (const Vector3& vector) const
{
	return Vector3 (x - vector.x, y - vector.y, z - vector.z);
}

/*******************************/

const Vector3 Vector3::operator * (const Real scalar) const
{
	return Vector3 (x * scalar, y * scalar, z * scalar);
}

/*******************************/

const Vector3 Vector3::operator / (const Real scalar) const
{
	return Vector3 (x / scalar, y / scalar, z / scalar);
}

/*******************************/

const Vector3 operator + (const Real scalar, const Vector3& vector)
{
	return vector + scalar;
}

/*******************************/

const Vector3 operator - (const Real scalar, const Vector3& vector)
{
	return vector - scalar;
}

/*******************************/

const Vector3 operator * (const Real scalar, const Vector3& vector)
{
	return vector * scalar;
}

/*******************************/

const Real Vector3::dot (const Vector3& vector) const
{
	return x * vector.x + y * vector.y + z * vector.z;
}

/*******************************/

const Vector3 Vector3::cross (const Vector3& vector) const
{
	return Vector3 (y * vector.z - z * vector.y, z * vector.x - x * vector.z, x * vector.y - y * vector.x);

}

/*******************************/

const Real Vector3::lengthSquared () const
{
	return dot (*this);
}

/*******************************/

const Real Vector3::length () const
{
	return Math::sqrt (lengthSquared ());
}

/*******************************/

const Vector3 Vector3::unit () const
{
	return (*this) / length ();
}

/*******************************/

void Vector3::normalize ()
{
	(*this) /= length ();
}

/*******************************/
